package com.bc.trade.service;


import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;

import com.bc.common.CommonEnum.OrderStatus;
import com.bc.common.PayType;
import com.bc.common.message.AccountBalanceChangeResp;
import com.bc.common.message.AccountTransferResp;
import com.bc.trade.model.Channel;
import com.bc.trade.model.TradeOrder;
import com.fs.common.util.FSDate;
import com.fs.common.util.FSJson;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.ICallback;

/**
 * 虚账服务类，提供加钱、减钱、转账操作
 * @author zhongzhanfeng
 *
 */
public class VirtualAccountService{
	
	/**
	 * 加钱
	 * * @param isD0  是否D0
	 * @param channelNo 渠道号
	 * @param accountNo 虚账账号
	 * @param amount 金额分
	 * @return
	 */
	public AccountBalanceChangeResp addMoney(boolean isD0, String channelNo, String accountNo, Integer amount) {
		AccountBalanceChangeResp changeBalanceRsp = changeBalance(isD0, channelNo, accountNo, amount);
		System.out.println("虚账返回 <--" + FSJson.toString(changeBalanceRsp));
		return changeBalanceRsp;
	}
	
	/**
	 * 减钱
	 * @param isD0  是否D0
	 * @param channelNo 渠道号
	 * @param accountNo 虚账账号
	 * @param amount 金额分
	 * @return
	 */
	public AccountBalanceChangeResp subMoney(boolean isD0, String channelNo, String accountNo, Integer amount) {
		AccountBalanceChangeResp changeBalanceRsp = changeBalance(isD0, channelNo, accountNo, -amount);
		System.out.println("虚账返回 <--" + FSJson.toString(changeBalanceRsp));
		return changeBalanceRsp;
	}
	
	public AccountBalanceChangeResp processVirtualAccount(TradeOrder order) {
		Channel channel = Channel.selectByChannelCode(order.getChannelCode());
		if(channel.getIsDirectClearing() == false && order.getIsInVirtualAccount() == false) {
			if(order.getPayType().equals(PayType.DF_PERSONAL) || order.getPayType().equals(PayType.DF_COMPANY)) {
				//代付失败，需要撤销回滚
				if(order.getOrderStatus().equals(OrderStatus.Fail.getValue())) {
					Integer amt = order.getAmount().intValue() + order.getMerchFee().intValue();
					return addMoney(order.getIsD0(), order.getChannelCode(), order.getMerchCode(), amt);
				}
			}
			
			if(order.getOrderStatus().equals(OrderStatus.Success.getValue())) {
				if((order.getPayType().equals(PayType.TRANSFER_QRCODE) 
						|| order.getPayType().equals(PayType.UNION_PAY) 
						|| order.getPayType().equals(PayType.QUICK_PAY_SET)
						|| PayType.ALIPAY_PUBLIC.equals(order.getPayType()) 
						|| PayType.WECHAT_PUBLIC.equals(order.getPayType())
						|| PayType.ALIPAY_QRCODE.equals(order.getPayType())
						|| PayType.WECHAT_QRCODE.equals(order.getPayType())
						|| PayType.WXGJPAY_PUBLIC.equals(order.getPayType())
						|| PayType.WXGJPAY_MICORPAY.equals(order.getPayType())
						|| PayType.WXGJPAY_QRCODE.equals(order.getPayType())
					) && order.getIsInVirtualAccount() == false) {
					Integer amt = order.getAmount().intValue() - order.getMerchFee().intValue();
					return addMoney(order.getIsD0(), order.getChannelCode(), order.getMerchCode(), amt);
				}
			}
		}
		
		//退款失败需要撤销
		if(order.getPayType().equals(PayType.REFUND) && order.getOrderStatus().equals(OrderStatus.Fail.getValue())) {
			boolean isD0 = true;
			TradeOrder originalOrder = TradeOrder.dao.selectByOrderNo(order.getOriginalOrderNo());
			if (!FSDate.getDate().equals(originalOrder.getSettleDate())) {
				isD0 = false;
			}
			Integer amt = order.getAmount().intValue() - order.getMerchFee().intValue();
			return addMoney(isD0, order.getChannelCode(), order.getMerchCode(), amt);
		}
		
		return null;
	}
	
	/**
	 * 操作虚账金额
	 * @param channelNo
	 * @param accountNo
	 * @param amount
	 * @return
	 */
	private AccountBalanceChangeResp changeBalance(boolean isD0, String channelNo,String accountNo,Integer amount){
		Object result = Db.execute(new ICallback() {
			@Override
			public Object call(Connection conn) throws SQLException {
				CallableStatement proc = conn.prepareCall("{ call balance_change_proc(?,?,?,?,?,?,?) }");
				proc.setBoolean(1, isD0);
				proc.setString(2, channelNo);
				proc.setString(3, accountNo);
				proc.setLong(4,amount.longValue());
				proc.registerOutParameter(5, java.sql.Types.VARCHAR);
				proc.registerOutParameter(6, java.sql.Types.BIGINT);
				proc.execute();
				AccountBalanceChangeResp rsp = new AccountBalanceChangeResp();
				rsp.setRespMsg(proc.getString(5));
				rsp.setRespCode(proc.getString(5));
				rsp.setBalance(proc.getString(6));
				rsp.setIsD0(proc.getBoolean(7));
				return rsp;
			}
		});
		return (AccountBalanceChangeResp) result;
	}
	
	/**
	 * 虚账转账
	 * @param channelNo 渠道号
	 * @param fromAccountNo 转出虚账账号
	 * @param toAccountNo 转入虚账账号
	 * @param amount 金额分
	 * @return
	 */
	public AccountTransferResp transfer(String channelNo,String fromAccountNo,String toAccountNo,Long amount){
		Object result = Db.execute(new ICallback() {
			@Override
			public Object call(Connection conn) throws SQLException {
				CallableStatement proc = conn.prepareCall("{ call transfer_proc(?,?,?,?,?,?,?) }");
				proc.setString(1, channelNo);
				proc.setString(2, fromAccountNo);
				proc.setString(3, toAccountNo);
				proc.setLong(4,amount);
				proc.registerOutParameter(5, java.sql.Types.BIGINT);
				proc.registerOutParameter(6, java.sql.Types.BIGINT);
				proc.registerOutParameter(7, java.sql.Types.VARCHAR);
				proc.execute();
				AccountTransferResp rsp = new AccountTransferResp();
				rsp.setFromAccountBalance(proc.getString(5));
				rsp.setToAccountBalance(proc.getString(6));
				rsp.setRespCode(proc.getString(7));
				rsp.setRespMsg(proc.getString(7));
				return rsp;
			}
		});
		return  (AccountTransferResp) result;
	}

}
